/**
 * 用户数据模型类，封装用户的用户名和密码信息
 */
public class User {
    // 私有成员变量：用户名、密码
    private String userName;
    private String password;

    // 无参构造方法（默认构造）
    public User() {}

    // 有参构造方法，用于创建用户对象时直接赋值用户名和密码
    public User(String userName, String password) {
        this.userName = userName;
        this.password = password;
    }

    // userName的getter方法：获取用户名
    public String getUserName() {
        return userName;
    }

    // userName的setter方法：设置用户名
    public void setUserName(String userName) {
        this.userName = userName;
    }

    // password的getter方法：获取密码
    public String getPassword() {
        return password;
    }

    // password的setter方法：设置密码
    public void setPassword(String password) {
        this.password = password;
    }
}
/**
 * 用户操作接口，定义用户管理系统的核心行为（添加用户、查询用户）
 * 所有用户操作的实现类需遵循此接口规范，体现面向接口编程的抽象层思想
 */
public interface UserDao {
    /**
     * 添加用户（对应注册功能）
     * @param user 待添加的用户对象（包含用户名和密码）
     * @return boolean：添加成功返回true，添加失败（如用户名已存在）返回false
     */
    boolean addUser(User user);

    /**
     * 根据用户名和密码查询用户（对应登录功能）
     * @param userName 待查询的用户名
     * @param password 待验证的密码
     * @return User：查询到匹配的用户返回该用户对象，未查询到返回null
     */
    User getUser(String userName, String password);
}
/**
 * UserDao接口的数组实现类，使用数组存储用户数据
 * 实现addUser（添加用户）和getUser（查询用户）的具体业务逻辑
 */
public class UserDaoForArray implements UserDao {
    // 数组：存储用户对象，初始容量设为10（可根据需求调整）
    private User[] data = new User[10];
    // 记录当前已存储的用户数量（用于数组扩容判断和遍历）
    private int count = 0;

    /**
     * 实现addUser方法：添加用户前先校验用户名是否已存在
     * @param user 待添加的用户对象
     * @return boolean：添加成功返回true，用户名已存在返回false
     */
    @Override
    public boolean addUser(User user) {
        // 1. 校验用户名是否已存在：遍历已存储的用户，对比用户名
        for (int i = 0; i < count; i++) {
            // 若当前用户的用户名与待添加用户的用户名一致（忽略大小写），则用户名已存在
            if (data[i].getUserName().equalsIgnoreCase(user.getUserName())) {
                return false; // 用户名已存在，添加失败
            }
        }

        // 2. 校验数组是否已满：若count等于数组长度，先扩容（扩容为原长度的2倍）
        if (count == data.length) {
            User[] newData = new User[data.length * 2];
            // 复制原数组数据到新数组
            System.arraycopy(data, 0, newData, 0, data.length);
            data = newData; // 指向新数组
        }

        // 3. 添加用户到数组，count自增
        data[count] = user;
        count++;
        return true; // 添加成功
    }

    /**
     * 实现getUser方法：根据用户名和密码查询匹配的用户
     * @param userName 待查询的用户名
     * @param password 待验证的密码
     * @return User：匹配则返回用户对象，不匹配返回null
     */
    @Override
    public User getUser(String userName, String password) {
        // 遍历已存储的用户，对比用户名和密码
        for (int i = 0; i < count; i++) {
            User currentUser = data[i];
            // 用户名完全匹配（忽略大小写）且密码完全匹配
            if (currentUser.getUserName().equalsIgnoreCase(userName) 
                && currentUser.getPassword().equals(password)) {
                return currentUser; // 返回匹配的用户对象
            }
        }
        return null; // 未找到匹配用户
    }
}

import java.util.Scanner;

/**
 * 应用层类，负责用户注册和登录的业务流程控制
 * 依赖UserDao接口（而非具体实现类），体现面向接口编程的核心思想
 */
public class Application {
    // 依赖UserDao接口（面向接口编程的关键：不依赖具体实现）
    private UserDao userDao;
    //  Scanner对象：用于获取用户输入
    private Scanner scanner = new Scanner(System.in);

    /**
     * 注入UserDao实现类对象（通过setter方法，实现依赖注入）
     * @param userDao 具体的UserDao实现类对象（如UserDaoForArray）
     */
    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }

    /**
     * 注册业务流程：获取用户输入→校验密码→调用UserDao添加用户→提示结果
     */
    public void register() {
        System.out.println("******注册用户******");
        // 1. 获取用户输入的用户名
        System.out.print("请输入用户名:");
        String userName = scanner.next();

        // 2. 获取用户输入的两次密码，并校验一致性
        System.out.print("请输入密码:");
        String pwd1 = scanner.next();
        System.out.print("请重新输入密码:");
        String pwd2 = scanner.next();

        // 3. 校验两次密码是否一致
        if (!pwd1.equals(pwd2)) {
            System.out.println("两次输入的密码不相符，请重新输入!");
            return; // 密码不一致，终止注册流程
        }

        // 4. 调用UserDao的addUser方法添加用户
        User user = new User(userName, pwd1);
        boolean isSuccess = userDao.addUser(user);

        // 5. 根据添加结果提示用户
        if (isSuccess) {
            System.out.println(userName + "，注册成功!");
        } else {
            System.out.println(userName + "，用户名已存在，请更换用户名!");
        }
    }

    /**
     * 登录业务流程：获取用户输入→调用UserDao查询用户→提示结果
     */
    public void login() {
        System.out.println("******用户登录******");
        // 1. 获取用户输入的用户名和密码
        System.out.print("请输入用户名:");
        String userName = scanner.next();
        System.out.print("请输入密码:");
        String password = scanner.next();

        // 2. 调用UserDao的getUser方法查询匹配用户
        User user = userDao.getUser(userName, password);

        // 3. 根据查询结果提示用户
        if (user != null) {
            System.out.println(userName + " 已登录");
        } else {
            System.out.println("账号或密码错误，请重新尝试!");
        }
    }

    /**
     * 主方法：程序入口，初始化对象→绑定接口实现→提供功能菜单
     */
    public static void main(String[] args) {
        // 1. 创建Application对象（应用层）和UserDaoForArray对象（底层实现）
        Application app = new Application();
        UserDao userDao = new UserDaoForArray();

        // 2. 注入UserDao实现类对象（关键：应用层仅依赖接口，不关注具体实现）
        app.setUserDao(userDao);

        // 3. 提供功能菜单，循环接收用户操作
        Scanner scanner = new Scanner(System.in);
        while (true) {
            System.out.println("\n=====用户管理系统=====");
            System.out.println("1. 注册");
            System.out.println("2. 登录");
            System.out.println("3. 退出");
            System.out.print("请选择功能（1-3）:");
            int choice = scanner.nextInt();

            // 根据用户选择执行对应功能
            switch (choice) {
                case 1:
                    app.register(); // 执行注册
                    break;
                case 2:
                    app.login(); // 执行登录
                    break;
                case 3:
                    System.out.println("系统已退出，感谢使用!");
                    scanner.close();
                    return; // 退出程序
                default:
                    System.out.println("输入错误，请选择1-3之间的数字!");
                    break;
            }
        }
    }
}
